package com.lan.parse;

import com.lan.ScriptContext;
import com.lan.antlr.ScriptBaseListener;
import com.lan.antlr.ScriptParser;
import com.lan.model.Type;
import com.lan.model.symbol.*;

import java.util.List;

public class VarListener extends ScriptBaseListener {

    private ScriptContext context;

    public VarListener(ScriptContext context) {
        this.context = context;
    }

    @Override
    public void enterVariableDeclarator(ScriptParser.VariableDeclaratorContext ctx) {
        Scope scope = context.nodeOfScope(ctx);
        if (scope != null) {
            String varName = ctx.variableDeclaratorId().name().getText();
            Variable variable = context.lookupVariable(scope, varName);
            if (variable == null) {
                variable = new Variable(scope.getId() + "_" + varName, varName, scope, ctx.variableDeclaratorId());
            }
            ScriptParser.VariableInitializerContext variableInitializerContext = ctx.variableInitializer();
            if (variableInitializerContext != null) {
                if (variableInitializerContext.function() != null) {
                    variable.setType(Type.Function);
                    Function function = context.lookupFunction(scope, varName);
                    variable.setValue(function);
                } else if (variableInitializerContext.json() != null) {
                    if (variableInitializerContext.json().obj() != null) {
                        variable.setType(Type.JSON);
                        Json json = context.lookupJson(scope, varName);
                        variable.setValue(json);
                    } else if (variableInitializerContext.json().arr() != null) {
                        variable.setType(Type.JArray);
                        Jarray jarray = context.lookupJarray(scope, varName);
                        variable.setValue(jarray);
                    }
                } else if (variableInitializerContext.expression() != null) {
                    varType(variable, variableInitializerContext);
                }
            }
            scope.add(variable);
        }
    }


    private void varType(Variable variable, ScriptParser.VariableInitializerContext variableInitializerContext) {
        if (variableInitializerContext.expression() != null) {
            if (variableInitializerContext.expression().primary() != null && variableInitializerContext.expression().primary().literal() != null) {
                ScriptParser.LiteralContext literalContext = variableInitializerContext.expression().primary().literal();
                if (literalContext.DECIMAL_LITERAL() != null) {
                    variable.setType(Type.Integer);
                    variable.setValue(Integer.valueOf(literalContext.DECIMAL_LITERAL().getText()));
                } else if (literalContext.FLOAT_LITERAL() != null) {
                    variable.setType(Type.Float);
                    variable.setValue(Float.valueOf(literalContext.FLOAT_LITERAL().getText()));
                } else if (literalContext.BOOL_LITERAL() != null) {
                    variable.setType(Type.Boolean);
                    variable.setValue(Boolean.valueOf(literalContext.BOOL_LITERAL().getText()));
                } else if (literalContext.str() != null) {
                    variable.setType(Type.String);
                    if (literalContext.str().name() != null) {
                        variable.setValue(literalContext.str().name());
                    }
                }
            }
        }
    }


    @Override
    public void enterParameters(ScriptParser.ParametersContext ctx) {
        ScriptParser.ParameterContext parameterContext = ctx.parameter();
        if (parameterContext == null) {
            return;
        }
        List<ScriptParser.VariableDeclaratorIdContext> variableDeclaratorIdContextList = parameterContext.variableDeclaratorId();
        if (variableDeclaratorIdContextList == null || variableDeclaratorIdContextList.size() == 0) {
            return;
        }

        Scope scope = context.nodeOfScope(ctx);
        if (scope instanceof Function) {
            Function function = (Function) scope;
            for (int i = 0; i < variableDeclaratorIdContextList.size(); i++) {
                ScriptParser.VariableDeclaratorIdContext variableDeclaratorIdContext = variableDeclaratorIdContextList.get(i);
                String varName = variableDeclaratorIdContext.name().getText();
                Variable variable = new Variable(scope.getId() + "_" + varName, varName, scope, variableDeclaratorIdContext);
                function.getParameters().add(variable);
            }
        }
    }

}
